package com.qf.netty.core;

import com.qf.netty.handler.TextFrameChannelHandler;
import com.qf.netty.handler.TextFrameOutChannelHandler;
import com.qf.netty.handler.base.BaseMsgChannelHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * Netty服务的启动类
 * author Ken
 * create_time 2023/1/4
 */
@Component
@Slf4j
public class NettyServer {

    private EventLoopGroup master = new NioEventLoopGroup();
    private EventLoopGroup slave = new NioEventLoopGroup();

    private ServerBootstrap serverBootstrap;

    @Value("${server.port}")
    private int port;

    /**
     * 从IOC容器中，找到所有的BaseMsgChannelHandler类型的Bean对象，注入到这个集合中
     */
    @Autowired(required = false)
    private List<BaseMsgChannelHandler> channelHandlers;

    /**
     * Netty服务的引导类初始化
     */
    @PostConstruct
    public void init(){
        log.info("[Netty Init] Netty服务进行初始化...");
        log.info("新版本的日志333333.....");
        //初始化Netty引导类
        serverBootstrap = new ServerBootstrap()
                .group(master, slave)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer() {
                    @Override
                    protected void initChannel(Channel ch) throws Exception {
                        //设置Channel管道的相关的Handler
                        ChannelPipeline pipeline = ch.pipeline();
                        //对Http协议和WebSocket协议的支持
                        pipeline.addLast(new HttpServerCodec());
                        pipeline.addLast(new HttpObjectAggregator(1024 * 1024 * 10));
                        pipeline.addLast(new WebSocketServerProtocolHandler("/", null, false, 1024 * 1024 * 10));
                        //添加自定义的ChannelHandler
                        pipeline.addLast(new TextFrameOutChannelHandler());
                        pipeline.addLast(new TextFrameChannelHandler());

                        //循环channelHandlers集合，添加到管道中
                        if (!CollectionUtils.isEmpty(channelHandlers)) {
                            for (BaseMsgChannelHandler channelHandler : channelHandlers) {
                                pipeline.addLast(channelHandler);
                            }
                        }
                    }
                });
    }

    /**
     * 启动Netty服务器
     */
    public void started(){
        //绑定端口并且启动服务
        //通过异步回调的方式监听绑定的结果
        serverBootstrap.bind(port).addListener(future -> {
            if (future.isSuccess()) {
                log.info("[Netty Server Start] Netty信令服务器启动成功！端口：" + port);
            } else {
                log.error("[Netty Server Error] Netty信令服务器启动失败！", future.cause());
            }
        });
    }
}
